package com.ug.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ug.common.constant.CommonConstants;
import com.ug.common.enums.ErrorCode;
import com.ug.common.exception.SystemException;
import com.ug.common.id.SnowFlakeFactory;
import com.ug.system.entity.SysRole;
import com.ug.system.entity.SysRoleUser;
import com.ug.system.entity.dto.QueryDto;
import com.ug.system.entity.dto.SysRoleDto;
import com.ug.system.mapper.SysRoleMapper;
import com.ug.system.service.SysRoleMenuService;
import com.ug.system.service.SysRoleService;
import com.ug.system.service.SysRoleUserService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author LY
 * @create 2024/7/16 15:55
 * @Description 角色服务实现层
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    private final SysRoleUserService roleUserService;

    private final SysRoleMenuService roleMenuService;

    @Override
    public IPage<SysRole> getRoleList(QueryDto queryDto, SysRoleDto sysRoleDto) {
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(SysRole::getCreateTime);
        if (StringUtils.isNotBlank(sysRoleDto.getRoleName())){
            queryWrapper.like(SysRole::getRoleName, sysRoleDto.getRoleName());
        }
        if (StringUtils.isNotBlank(sysRoleDto.getRoleCode())){
            queryWrapper.like(SysRole::getRoleCode, sysRoleDto.getRoleCode());
        }
        queryWrapper.ne(SysRole::getRoleCode, CommonConstants.ROLE_ADMIN);
        Page<SysRole> page = new Page<>();
        page.setCurrent(queryDto.getCurrentPage());
        page.setSize(queryDto.getSize());
        return baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    public void editRole(SysRole role) {
        //  校验角色代码及名称
        checkRole(role);
        if (role.getRoleId() != null){
            baseMapper.updateById(role);
        } else {
            role.setRoleId(SnowFlakeFactory.getSnowFlakeFromCache().nextId());
            baseMapper.insert(role);
        }
    }

    @Override
    public void delRole(Long roleId) {
        //  校验角色是否已绑定用户
        checkRoleUser(roleId);
        //  先把与角色绑定的菜单删除
        roleMenuService.deleteByRoleId(roleId);
        //  再删除角色
        baseMapper.deleteById(roleId);
    }

    @Override
    public List<SysRole> getRoleByUserId(Long userId) {
        return baseMapper.getRoleByUserId(userId);
    }

    @Override
    public List<GrantedAuthority> getRolesByUser(Long userId) {
        Set<String> permissions = new HashSet<>();
        List<SysRole> roleList = baseMapper.getRoleByUserId(userId);
        if (!CollectionUtils.isEmpty(roleList)){
            for (SysRole sysRole : roleList) {
                permissions.add(sysRole.getRoleCode());
            }
        }
        return permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
    }

    @Override
    public SysRole getRoleByCode(String code) {
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getRoleCode, code);
        return baseMapper.selectOne(wrapper);
    }

    /**
     * 校验角色是否已绑定用户
     * @param roleId 角色id
     */
    private void checkRoleUser(Long roleId){
        List<SysRoleUser> list = roleUserService.getRoleUserByRoleId(roleId);
        if (!CollectionUtils.isEmpty(list)){
            throw new SystemException(ErrorCode.ROLE_BIND_ERROR);
        }
    }

    /**
     * 校验角色名称和角色代码
     * @param role 角色信息
     */
    private void checkRole(SysRole role){
        List<SysRole> list;
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        if (role.getRoleId() != null){
            wrapper.ne(SysRole::getRoleId, role.getRoleId());
        }
        wrapper.and(w -> w.eq(SysRole::getRoleName, role.getRoleName()).or().eq(SysRole::getRoleCode, role.getRoleCode()));
        list = baseMapper.selectList(wrapper);
        if (list != null && !list.isEmpty()){
            throw new SystemException(ErrorCode.ROLE_REPETITION_ERROR);
        }
    }
}
